package domain;

import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.session.SqlSession;

import java_persistence.AppointmentMapper;
import java_persistence.DoctorMapper;
import java_persistence.PatientMapper;
import java_persistence.UserMapper;

/**
 * @author joseph simoneau <simoneau@gatech.edu>
 *
 */
public class Appointment {

	private String date;
	private String complaint;
	private Doctor requested_doctor;
	private Patient patient;
	private TreatmentRecord treatment_record;

	public Appointment() {
		super();

		this.date = null;
		this.complaint = null;
		this.requested_doctor = null;
		this.patient = null;
		this.treatment_record = null;
		
	}
	
	public Appointment( String d, String c, Doctor rd, Patient p, TreatmentRecord tr) {
		super();
		
		this.date = d;
		this.complaint = c;
		this.requested_doctor = rd;
		this.patient = p;
		this.treatment_record = tr;
	}
	
	//Getters are simple enough.
	public String getDate() {
		return date;
	}
	public String getComplaint() {
		return complaint;
	}
	public Doctor getRequested_doctor() {
		return requested_doctor;
	}
	public Patient getPatient() {
		return patient;
	}
	public TreatmentRecord getTreatment_record() {
		return treatment_record;
	}

	//setters work just like normal POJOs.  
	public void setDate(String date) {
		this.date = date;
	}
	public void setComplaint(String complaint) {
		this.complaint = complaint;
	}
	public void setRequested_doctor(Doctor requested_doctor) {
		this.requested_doctor = requested_doctor;
	}
	public void setPatient(Patient patient) {
		this.patient = patient;
	}
	public void setTreatment_record(TreatmentRecord treatment_record) {
		this.treatment_record = treatment_record;
	}
	

	// CREATES
	
	/**Saves 'this' to the database.  If auto-commit is not enabled, follow this method call with a call to 'your SqlSession object'.commit()
	 * @param amap an AppointentMapper object associated with a current, open SqlSession object.
	 */
	public void create(AppointmentMapper amap) {
		if( this.patient.getUsername() != null && this.date != null ) {
			amap.create( this.date, this.complaint, this.requested_doctor.getUsername(), this.patient.getUsername());
		}
	}
	
	// RETRIEVES
	
	/**Retrieves an Appointment entity from the database and replaces the contents of 'this' with that
	 * from the database.  If the date and patient_username are not specified correctly, all members of 'this' will
	 * be null if such an Appointment does not exist or garbage if it does.
	 * @param date A String representing the date of the appointment you wish to fetch in the format "YYYY-MM-DD HH:MM:SS" 
	 * @param patient_username a String representing the patient's username.
	 * @param session the open, connected SqlSession object.
	 */
	public void retrieve(String date, String patient_username, SqlSession session) {
		PatientMapper pmap = session.getMapper(PatientMapper.class);
		UserMapper umap = session.getMapper(UserMapper.class);
		DoctorMapper dmap = session.getMapper(DoctorMapper.class);
		AppointmentMapper amap = session.getMapper(AppointmentMapper.class);
		
		this.date = date;
		this.patient = pmap.get_patient_by_username(patient_username);
		
		String rd_username = amap.get_requested_doctor_username(date, patient_username);
		
		//this.requested_doctor = (Doctor) umap.get_user_by_username(rd_username);
		this.requested_doctor = dmap.get_doctor_by_username(rd_username);

		this.complaint = amap.get_complaint(date, patient_username);

		if( this.treatment_record == null) this.treatment_record = new TreatmentRecord();
		this.treatment_record.retrieve(date, patient_username, session);
		
	}
	
	/**Retrieves the dates of all past and future appointments scheduled by user patient_username from the database.
	 * @param patient_username The username of the patient.
	 * @param session The valid, open SqlSession object
	 * @return a List<String> where each element represents a date the patient has/had an appointment of the format "YYYY-MM-DD HH:MM:SS", a 0-element List if there are none or if patient_username isn't a patient. 
	 */
	public static List<String> get_appointment_dates(String patient_username, SqlSession session) {
		
		List<String> ret = new ArrayList<String>();
		
		ret = session.getMapper(AppointmentMapper.class).get_appointment_dates(patient_username);
		
		
		return ret;
	}
	
	/**Retrieves all past and future appointments scheduled by user patient_username from the database.  
	 * @param patient_username The username of the patient.
	 * @param session the valid, open SqlSession object.
	 * @return A List<Appointment> where each element represents an appointment the patient has/had or a 0-element List if the patient has no appointments or isn't a patient. 
	 */
	public static List<Appointment> get_appointments(String patient_username, SqlSession session) {
		List<Appointment> ret = new ArrayList<Appointment>();
		List<String> dates = Appointment.get_appointment_dates(patient_username, session);
		
		for( String i: dates) {
			Appointment temp = new Appointment();
			temp.retrieve(i, patient_username, session);
			
			ret.add(temp);
		}
		
		return ret;
	}
	
	// UPDATES
	
	/**Updates 'this''s entry in the database.  Please note that it is not possible to change the date and patient_username fields, as those two fields uniquely identify each appointment to the database.  Attempingt to do so will cause a database error.
	 * @param amap AppointmentMapper object. retrieved from a valid, open SqlSession object 
	 */
	public void update(AppointmentMapper amap) {
		if( this.patient.getUsername() != null && this.date != null ) {
			amap.update( this.date, this.complaint, this.requested_doctor.getUsername(), this.patient.getUsername());
		}
	}
	
	// DELETES
	
	/**Deletes 'this''s entry from the database.  While this should not be done to eliminate records, it is provided for testing purposes and for the ability to change the date of an appointment (by deleting it and creating a new one).    
	 * @param amap AppointmentMapper object retrieved from a valid, open SqlSession object.
	 */
	public void delete(AppointmentMapper amap) {
		amap.delete( this.date, this.patient.getUsername() );
	}
	
	
}